/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * FrameICQ.java
 *
 * Created on 27.05.2011, 11:24:56
 */
package ru.icq.gui.frame;

import java.awt.Component;
import java.io.File;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import org.apache.log4j.Logger;
import ru.icq.accounts.GeneralAccountjICQ;
import ru.icq.exceptions.PropertiesExceptions;
import ru.icq.gui.dialogs.DialogChats;
import ru.icq.gui.dialogs.DialogSelectUsers;
import ru.icq.gui.dialogs.DialogSettings;
import ru.icq.gui.frame.renderer.MyTreeCellRenderer;
import ru.icq.io.FileProperties;
import ru.icq.io.connections.ConnectionsCustom;
import ru.icq.accounts.EntryjICQ;
import ru.icq.accounts.GroupjICQ;
import ru.icq.io.loadTheme;
import ru.icq.listener.IAccountListener;
import ru.icq.users.AccountUser;
import ru.icq.utils.Utils;

/**
 * Еще одна попытка написать клиента ICQ.
 * GeneralAccountjICQ:
 *  - Соединение
 *  - Разрыв соединения
 *  - Смена статуса
 * 
 * FrameICQ:
 *  - Соединение
 *  - Разрыв соединения
 *  - Прием сообщения
 *  - Смена статуса
 * 
 * PanelChat:
 *  - Открытие чата
 *  - Закрытие чата
 *  - Отправка сообщения
 *  - Прием сообщения
 * 
 * @author Носов А.В.
 */
public class FrameICQ extends javax.swing.JFrame implements IAccountListener {

    // Variables declaration
    private static final Logger log = Logger.getLogger(FrameICQ.class);
    
    private Map users = new HashMap();
    private Properties prop;
    private AccountUser user = null;
    
    private DefaultMutableTreeNode modelNode = new DefaultMutableTreeNode("UserInfo");
    private DefaultTreeModel modelTree = new DefaultTreeModel(modelNode);
    
    DialogChats dialogChats = null;
    // End of variables declaration

    /** Creates new form FrameICQ */
    public FrameICQ() {
        try {
            prop = FileProperties.loadProperties();
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (PropertiesExceptions ex) {
            log.error("Ошибка загрузки настроект:", ex);
        } catch (Exception ex) {
            log.error("ОЙ!", ex);
            Utils.isShowErrorMessage( (Component)this, "Это фича такая. Перегрузите приложение!!!");
        }
        users = FileProperties.getUsers();
        
        initComponents();
        
        if (prop != null) {
            if (prop.getProperty("jICQ.window.x") != null &&
                prop.getProperty("jICQ.window.y") != null &&
                prop.getProperty("jICQ.window.width") != null &&
                prop.getProperty("jICQ.window.height") != null) {
                    try {
                        int x = Integer.parseInt(prop.getProperty("jICQ.window.x").trim());
                        int y = Integer.parseInt(prop.getProperty("jICQ.window.y").trim());
                        int width = Integer.parseInt(prop.getProperty("jICQ.window.width").trim());
                        int height = Integer.parseInt(prop.getProperty("jICQ.window.height").trim());
                        this.setBounds(x, y, width, height);
                    } catch (NumberFormatException ex) {
                        Utils.setFrameCenter( (Component)this );
                        log.error("Ошибка настройки расположения окна.");
                    }
            } else Utils.setFrameCenter( (Component)this );
            if (prop.getProperty("jICQ.extendedState") != null)
                this.setExtendedState(Integer.parseInt(prop.getProperty("jICQ.extendedState").trim()));
        }
        
        
        if (prop != null) {
            if (prop.getProperty("jICQ.last_user") != null) { 
                if (users.size() > 0) {
                    if (users.get(prop.getProperty("jICQ.last_user")) != null) {
                        user = new AccountUser(prop.getProperty("jICQ.last_user"));
                        loadUser();
                        return;
                    }
                }
            }
        }
        if (user == null) menuItemChangeActionPerformed(null);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        popupMenu = new javax.swing.JPopupMenu();
        menuItemSettings = new javax.swing.JMenuItem();
        menuItemChange = new javax.swing.JMenuItem();
        separatorMenu1 = new javax.swing.JPopupMenu.Separator();
        menuItemExit = new javax.swing.JMenuItem();
        panelMenuICQ = new javax.swing.JPanel();
        panelInfo = new javax.swing.JPanel();
        buttonInfo = new javax.swing.JButton();
        labelContactCount = new javax.swing.JLabel();
        panelMenu = new javax.swing.JPanel();
        buttonMenu = new javax.swing.JButton();
        buttonContact = new javax.swing.JToggleButton();
        buttonGroup = new javax.swing.JToggleButton();
        buttonSound = new javax.swing.JToggleButton();
        scrollPaneContacts = new javax.swing.JScrollPane();
        treeAccountsUser = new javax.swing.JTree();
        panelAccountsMenu = new javax.swing.JPanel();
        panelAccountsButton = new javax.swing.JPanel();

        menuItemSettings.setText("Settings");
        menuItemSettings.setName("menu.settings"); // NOI18N
        menuItemSettings.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemSettingsActionPerformed(evt);
            }
        });
        popupMenu.add(menuItemSettings);

        menuItemChange.setText("Change Accaunt");
        menuItemChange.setName("menu.change"); // NOI18N
        menuItemChange.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemChangeActionPerformed(evt);
            }
        });
        popupMenu.add(menuItemChange);
        popupMenu.add(separatorMenu1);

        menuItemExit.setText("Exit");
        menuItemExit.setName("menu.exit"); // NOI18N
        menuItemExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemExitActionPerformed(evt);
            }
        });
        popupMenu.add(menuItemExit);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setName("jICQ"); // NOI18N

        panelMenuICQ.setLayout(new java.awt.BorderLayout());

        panelInfo.setLayout(new javax.swing.BoxLayout(panelInfo, javax.swing.BoxLayout.LINE_AXIS));

        buttonInfo.setText("Info");
        buttonInfo.setName("menu.info"); // NOI18N
        panelInfo.add(buttonInfo);
        buttonInfo.getAccessibleContext().setAccessibleName("");

        labelContactCount.setText("0");
        labelContactCount.setName("menu.contactCounts"); // NOI18N
        panelInfo.add(labelContactCount);

        panelMenuICQ.add(panelInfo, java.awt.BorderLayout.LINE_END);

        panelMenu.setLayout(new javax.swing.BoxLayout(panelMenu, javax.swing.BoxLayout.X_AXIS));

        buttonMenu.setText("menu");
        buttonMenu.setName("menu.menu"); // NOI18N
        buttonMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonMenuActionPerformed(evt);
            }
        });
        panelMenu.add(buttonMenu);
        buttonMenu.getAccessibleContext().setAccessibleName("");

        buttonContact.setText("Contacts");
        buttonContact.setName("menu.contacts"); // NOI18N
        panelMenu.add(buttonContact);
        buttonContact.getAccessibleContext().setAccessibleName("");

        buttonGroup.setText("Groups");
        buttonGroup.setName("menu.groups"); // NOI18N
        buttonGroup.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonGroupActionPerformed(evt);
            }
        });
        panelMenu.add(buttonGroup);
        buttonGroup.getAccessibleContext().setAccessibleName("");

        buttonSound.setText("Sound");
        buttonSound.setName("menu.sound"); // NOI18N
        panelMenu.add(buttonSound);
        buttonSound.getAccessibleContext().setAccessibleName("");

        panelMenuICQ.add(panelMenu, java.awt.BorderLayout.LINE_START);

        getContentPane().add(panelMenuICQ, java.awt.BorderLayout.PAGE_START);

        treeAccountsUser.setModel(modelTree);
        treeAccountsUser.setName("menu.accountsUsersTree"); // NOI18N
        treeAccountsUser.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                treeAccountsUserMouseClicked(evt);
            }
        });
        MyTreeCellRenderer rendere = new MyTreeCellRenderer();
        treeAccountsUser.setCellRenderer(rendere);
        scrollPaneContacts.setViewportView(treeAccountsUser);

        getContentPane().add(scrollPaneContacts, java.awt.BorderLayout.CENTER);

        panelAccountsMenu.setLayout(new java.awt.BorderLayout());

        panelAccountsButton.setLayout(new javax.swing.BoxLayout(panelAccountsButton, javax.swing.BoxLayout.X_AXIS));
        panelAccountsMenu.add(panelAccountsButton, java.awt.BorderLayout.LINE_END);

        getContentPane().add(panelAccountsMenu, java.awt.BorderLayout.PAGE_END);

        getAccessibleContext().setAccessibleName("jICQ");

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void buttonMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMenuActionPerformed
        popupMenu.show(buttonMenu, buttonMenu.getX(), buttonMenu.getY()+buttonMenu.getWidth());
    }//GEN-LAST:event_buttonMenuActionPerformed

    private void menuItemSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemSettingsActionPerformed
        DialogSettings s = new DialogSettings(this, true);
        s.setTheme(new loadTheme(user.getTheme(), "Russian"));
        s.setVisible(true);
    }//GEN-LAST:event_menuItemSettingsActionPerformed

    private void menuItemExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemExitActionPerformed
        Component[] components = panelAccountsButton.getComponents();
        for (Component component : components) {
            if (component instanceof GeneralAccountjICQ) {
                GeneralAccountjICQ a = (GeneralAccountjICQ) component;
                a.menuItemOffLineActionPerformed(evt);
            }
        }
        closeFrameJICQ();
    }//GEN-LAST:event_menuItemExitActionPerformed

    private void menuItemChangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemChangeActionPerformed
        new DialogSelectUsers().setVisible(true);
        closeFrameJICQ();
    }//GEN-LAST:event_menuItemChangeActionPerformed

private void treeAccountsUserMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_treeAccountsUserMouseClicked
    TreePath path = treeAccountsUser.getPathForLocation(evt.getPoint().x, evt.getPoint().y);
    treeAccountsUser.setSelectionPath(path);
    if ((evt.getClickCount() == 2) && (evt.getButton() == 1)) {
        DefaultMutableTreeNode selectNode = 
                (DefaultMutableTreeNode) treeAccountsUser.getLastSelectedPathComponent();
        if (selectNode != null) {
            if (selectNode.getUserObject() instanceof EntryjICQ) {
                if (dialogChats == null)
                    dialogChats = new DialogChats(this, false);
                
//                EntryjICQ e = (EntryjICQ) selectNode.getUserObject();
//                log.info(e.toString());
                dialogChats.setVisible(true);
                dialogChats.addChat( (EntryjICQ) selectNode.getUserObject() );
            }
        }
    }
}//GEN-LAST:event_treeAccountsUserMouseClicked

private void buttonGroupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGroupActionPerformed
        
}//GEN-LAST:event_buttonGroupActionPerformed

    /**
     * Загрузка информации о прользователе.
     */
    private void loadUser() {
        user.setFile( (File) users.get(user.getName()) );
        log.info(user.getFile().getAbsolutePath());
        
        Properties propAcc = FileProperties.loadProperties(
                user.getFile().getAbsolutePath() + File.separator + "settings.properties");
        user.setTheme(propAcc.getProperty("jICQ.theme"));
        
        user.setAccounts(FileProperties.getAccounts(user.getFile().getAbsoluteFile()));
        
        this.setTitle(user.getName());
//        log.info(user.toString());
        
        // TODO Нет загрузки языка
        loadTheme theme = new loadTheme(user.getTheme(), "Russian");
        theme.setTheme( (Component)this );
        theme.setTheme( (Component)popupMenu );
        
        //
        Iterator<GeneralAccountjICQ> it = user.getAccounts().values().iterator();
        while (it.hasNext()) {            
            GeneralAccountjICQ account = it.next();
            account.setTheme(theme);
            account.AddStatusConnection(this);
            //JLabel lab = new JLabel(account.getUid(), theme.getIcon("account.icq"), JLabel.CENTER);
            DefaultMutableTreeNode accountName = new DefaultMutableTreeNode(account);
            accountName.setAllowsChildren(true);
            modelTree.setAsksAllowsChildren(true);
            modelTree.insertNodeInto(accountName, modelNode, modelNode.getChildCount());
            panelAccountsButton.add(account);
        }
    }

    /**
     * Закрытие приложения.
     */
    private void closeFrameJICQ() {
        this.dispose();
    }

    /**
     * Устанавливает выбранного пользователя.
     * @param user пользователь
     */
    public void setSelectUser(String user) {
        this.user = new AccountUser(user);
    }

    /**
     * Возвращает выбранного пользователя.
     * @return пользователь
     */
    public AccountUser getSelectUser() {
        return user;
    }

    @Override
    public void changePresence(ConnectionsCustom connection) {
        switch (connection.getPresenceJICQ()) {
            case OFF_LINE:
                log.info("ВЫХОД");
                break;
            case ON_LINE:
                DefaultMutableTreeNode accountName = findTreeNode(modelNode, connection.getID());
                DefaultMutableTreeNode accountGroup = null;
                DefaultMutableTreeNode accountUser = null;
                if (accountName == null) {
                    accountName = new DefaultMutableTreeNode(connection.getID());
                    modelTree.insertNodeInto(accountName, modelNode, modelNode.getChildCount());
                }
                List<EntryjICQ> entrys = connection.displayBuddyList();
                for (EntryjICQ entry : entrys) {
                    Collection<GroupjICQ> groups = entry.getGroup();
                    for (GroupjICQ group : groups) {
                        accountGroup = findTreeNode(accountName, group.getName());
                        if (accountGroup == null) {
                            accountGroup = new DefaultMutableTreeNode(group);
                            modelTree.insertNodeInto(accountGroup, accountName, accountName.getChildCount());
                        }
                    }
                    accountUser = findTreeNode(accountGroup, entry.getUser());
                    if (accountUser == null) {
                        accountUser = new DefaultMutableTreeNode(entry);
                        modelTree.insertNodeInto(accountUser, accountGroup, accountGroup.getChildCount());
                    }
                }
                break;
            default:
        }
//        log.info("Спрашиваем список контактов");
    }

    private DefaultMutableTreeNode findTreeNode(TreeNode tree, String id) {
        
        Enumeration enumeration = tree.children();
        while (enumeration.hasMoreElements()) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement();
            Object obj = node.getUserObject();
            if (obj instanceof GeneralAccountjICQ) {
                GeneralAccountjICQ c = (GeneralAccountjICQ) obj;
                if (c.getID().equals(id))
                    return node;
            } else if (obj instanceof GroupjICQ) {
                GroupjICQ g = (GroupjICQ) obj;
                if (g.getName().equals(id)) {
                    return node;
                }
            } else if (obj instanceof EntryjICQ) {
                EntryjICQ e = (EntryjICQ) obj;
                if (e.getUser().equals(id)) {
                    return node;
                }
            }
        }
        return null;
    }

    @Override
    public void processChatMessage(String from, String msg) {
        log.info("Пришло сообщение от " + from + ": " + msg);
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new FrameICQ().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JToggleButton buttonContact;
    private javax.swing.JToggleButton buttonGroup;
    private javax.swing.JButton buttonInfo;
    private javax.swing.JButton buttonMenu;
    private javax.swing.JToggleButton buttonSound;
    private javax.swing.JLabel labelContactCount;
    private javax.swing.JMenuItem menuItemChange;
    private javax.swing.JMenuItem menuItemExit;
    private javax.swing.JMenuItem menuItemSettings;
    private javax.swing.JPanel panelAccountsButton;
    private javax.swing.JPanel panelAccountsMenu;
    private javax.swing.JPanel panelInfo;
    private javax.swing.JPanel panelMenu;
    private javax.swing.JPanel panelMenuICQ;
    private javax.swing.JPopupMenu popupMenu;
    private javax.swing.JScrollPane scrollPaneContacts;
    private javax.swing.JPopupMenu.Separator separatorMenu1;
    private javax.swing.JTree treeAccountsUser;
    // End of variables declaration//GEN-END:variables
}
